package flatlandRPG;

import java.util.LinkedList;

/**
 * Represents the world our character will exist and interact in. We should
 * start considering how we will control loading maps dynamically from disk (as
 * opposed to defining them in the code). Also, we need to consider collision,
 * scale and movement.
 *
 * @author Carlos Vializ (cvializ)
 * @author Evan Tatarka (evant)
 * @version 2011.04.05
 */
public class Map
    extends Entity
{
    /**
     * A list of all map objects that must be drawn. Use a linked list, so it's
     * not computationally expensive to remove items on the fly, in case they
     * get destroyed or something
     */
    private LinkedList<Entity> mapObjects;
    private CollisionManager   collisionManager;
    private ActorManager actorManager;
    private Player             player;


    /**
     * Instantiate a map object
     */
    public Map()
    {
        super();
        mapObjects = new LinkedList<Entity>();
        collisionManager = new CollisionManager();
    }


    // ----------------------------------------------------------
    /**
     * Adds the entity to the map to draw and update.
     *
     * @param entity
     *            the entity to add
     */
    public void add(Entity entity)
    {
        mapObjects.add(entity);

        if (entity instanceof Player)
        {
            player = (Player)entity;
            actorManager = new ActorManager(player);
        }

        if (entity instanceof IMoveable)
        {
            collisionManager.add((IMoveable)entity);
        }

        if (entity instanceof ISolid)
        {
            collisionManager.add((ISolid)entity);
        }

        if (entity instanceof Actor) {
            actorManager.add((Actor) entity);
        }
    }


    // ----------------------------------------------------------
    /**
     * Adds a list of entities to the map to draw and update.
     *
     * @param entities
     *            the entities to add
     */
    public void add(Iterable<Entity> entities)
    {
        for (Entity entity : entities)
        {
            add(entity);
        }
    }

    // ----------------------------------------------------------
    /**
     * Returns the player object.
     *
     * @return the player
     */
    public Player getPlayer()
    {
        return player;
    }


    // ----------------------------------------------------------
    /**
     * Returns a Linked list of entities that the map draws.
     *
     * @return the Entities
     */
    public LinkedList<Entity> getEntities()
    {
        return mapObjects;
    }

    // ----------------------------------------------------------
    /**
     * Updates the state of all the relevant entities of the map.
     */
    public void doLogic()
    {
        for (Entity e : mapObjects)
        {
            if (e instanceof ILogic)
            {
                ((ILogic)e).doLogic();
            }
        }

        collisionManager.doLogic();
        actorManager.doLogic();
    }


    // ----------------------------------------------------------
    /**
     * Draws all the relevant entities of the map.
     */
    public void draw()
    {
        for (Entity e : mapObjects)
        {
            if (e instanceof IDrawable)
            {
                ((IDrawable)e).draw();
            }
        }
        player.draw();
        actorManager.draw();
    }
}
